home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / sound / tms5220.c < prev    next >
C/C++ Source or Header  |  2000-02-15  |  21KB  |  703 lines

  1. /**********************************************************************************************
  2.  
  3.      TMS5220 simulator
  4.  
  5.      Written for MAME by Frank Palazzolo
  6.      With help from Neill Corlett
  7.      Additional tweaking by Aaron Giles
  8.  
  9. ***********************************************************************************************/
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <math.h>
  14.  
  15. #include "driver.h"
  16. #include "tms5220.h"
  17.  
  18.  
  19. /* Pull in the ROM tables */
  20. #include "tms5220r.c"
  21.  
  22.  
  23. /* these contain data that describes the 128-bit data FIFO */
  24. #define FIFO_SIZE 16
  25. static unsigned char fifo[FIFO_SIZE];
  26. static int fifo_head;
  27. static int fifo_tail;
  28. static int fifo_count;
  29. static int bits_taken;
  30.  
  31.  
  32. /* these contain global status bits */
  33. static int speak_external;
  34. static int talk_status;
  35. static int buffer_low;
  36. static int buffer_empty;
  37. static int irq_pin;
  38.  
  39. static void (*irq_func)(int state);
  40.  
  41.  
  42. /* these contain data describing the current and previous voice frames */
  43. static unsigned short old_energy = 0;
  44. static unsigned short old_pitch = 0;
  45. static int old_k[10] = {0,0,0,0,0,0,0,0,0,0};
  46.  
  47. static unsigned short new_energy = 0;
  48. static unsigned short new_pitch = 0;
  49. static int new_k[10] = {0,0,0,0,0,0,0,0,0,0};
  50.  
  51.  
  52. /* these are all used to contain the current state of the sound generation */
  53. static unsigned short current_energy = 0;
  54. static unsigned short current_pitch = 0;
  55. static int current_k[10] = {0,0,0,0,0,0,0,0,0,0};
  56.  
  57. static unsigned short target_energy = 0;
  58. static unsigned short target_pitch = 0;
  59. static int target_k[10] = {0,0,0,0,0,0,0,0,0,0};
  60.  
  61. static int interp_count = 0;       /* number of interp periods (0-7) */
  62. static int sample_count = 0;       /* sample number within interp (0-24) */
  63. static int pitch_count = 0;
  64.  
  65. static int u[11] = {0,0,0,0,0,0,0,0,0,0,0};
  66. static int x[10] = {0,0,0,0,0,0,0,0,0,0};
  67.  
  68. static int randbit = 0;
  69.  
  70.  
  71. /* Static function prototypes */
  72. static void process_command(void);
  73. static int extract_bits(int count);
  74. static int parse_frame(int removeit);
  75. static void check_buffer_low(void);
  76. static void set_interrupt_state(int state);
  77.  
  78.  
  79. /*#define DEBUG_5220*/
  80. #ifdef DEBUG_5220
  81.     static FILE *f;
  82. #endif
  83.  
  84.  
  85. /**********************************************************************************************
  86.  
  87.      tms5220_reset -- resets the TMS5220
  88.  
  89. ***********************************************************************************************/
  90.  
  91. void tms5220_reset(void)
  92. {
  93.     /* initialize the FIFO */
  94.     memset(fifo, 0, sizeof(fifo));
  95.     fifo_head = fifo_tail = fifo_count = bits_taken = 0;
  96.  
  97.     /* initialize the chip state */
  98.     speak_external = talk_status = buffer_empty = irq_pin = 0;
  99.     buffer_low = 1;
  100.  
  101.     /* initialize the energy/pitch/k states */
  102.     old_energy = new_energy = current_energy = target_energy = 0;
  103.     old_pitch = new_pitch = current_pitch = target_pitch = 0;
  104.     memset(old_k, 0, sizeof(old_k));
  105.     memset(new_k, 0, sizeof(new_k));
  106.     memset(current_k, 0, sizeof(current_k));
  107.     memset(target_k, 0, sizeof(target_k));
  108.  
  109.     /* initialize the sample generators */
  110.     interp_count = sample_count = pitch_count = 0;
  111.     randbit = 0;
  112.     memset(u, 0, sizeof(u));
  113.     memset(x, 0, sizeof(x));
  114.  
  115.     #ifdef DEBUG_5220
  116.         f = fopen("tms.log", "w");
  117.     #endif
  118. }
  119.  
  120.  
  121.  
  122. /**********************************************************************************************
  123.  
  124.      tms5220_reset -- reset the TMS5220
  125.  
  126. ***********************************************************************************************/
  127.  
  128. void tms5220_set_irq(void (*func)(int))
  129. {
  130.     irq_func = func;
  131. }
  132.  
  133.  
  134. /**********************************************************************************************
  135.  
  136.      tms5220_data_write -- handle a write to the TMS5220
  137.  
  138. ***********************************************************************************************/
  139.  
  140. void tms5220_data_write(int data)
  141. {
  142.     /* add this byte to the FIFO */
  143.     if (fifo_count < FIFO_SIZE)
  144.     {
  145.         fifo[fifo_tail] = data;
  146.         fifo_tail = (fifo_tail + 1) % FIFO_SIZE;
  147.         fifo_count++;
  148.  
  149.         #ifdef DEBUG_5220
  150.             if (f) fprintf(f, "Added byte to FIFO (size=%2d)\n", fifo_count);
  151.         #endif
  152.     }
  153.     else
  154.     {
  155.         #ifdef DEBUG_5220
  156.             if (f) fprintf(f, "Ran out of room in the FIFO!\n");
  157.         #endif
  158.     }
  159.  
  160.     /* update the buffer low state */
  161.     check_buffer_low();
  162. }
  163.  
  164.  
  165. /**********************************************************************************************
  166.  
  167.      tms5220_status_read -- read status from the TMS5220
  168.  
  169.       From the data sheet:
  170.         bit 0 = TS - Talk Status is active (high) when the VSP is processing speech data.
  171.                 Talk Status goes active at the initiation of a Speak command or after nine
  172.                 bytes of data are loaded into the FIFO following a Speak External command. It
  173.                 goes inactive (low) when the stop code (Energy=1111) is processed, or
  174.                 immediately by a buffer empty condition or a reset command.
  175.         bit 1 = BL - Buffer Low is active (high) when the FIFO buffer is more than half empty.
  176.                 Buffer Low is set when the "Last-In" byte is shifted down past the half-full
  177.                 boundary of the stack. Buffer Low is cleared when data is loaded to the stack
  178.                 so that the "Last-In" byte lies above the half-full boundary and becomes the
  179.                 ninth data byte of the stack.
  180.         bit 2 = BE - Buffer Empty is active (high) when the FIFO buffer has run out of data
  181.                 while executing a Speak External command. Buffer Empty is set when the last bit
  182.                 of the "Last-In" byte is shifted out to the Synthesis Section. This causes
  183.                 Talk Status to be cleared. Speed is terminated at some abnormal point and the
  184.                 Speak External command execution is terminated.
  185.  
  186. ***********************************************************************************************/
  187.  
  188. int tms5220_status_read(void)
  189. {
  190.     /* clear the interrupt pin */
  191.     set_interrupt_state(0);
  192.  
  193.     #ifdef DEBUG_5220
  194.         if (f) fprintf(f, "Status read: TS=%d BL=%d BE=%d\n", talk_status, buffer_low, buffer_empty);
  195.     #endif
  196.  
  197.     return (talk_status << 7) | (buffer_low << 6) | (buffer_empty << 5);
  198. }
  199.  
  200.  
  201.  
  202. /**********************************************************************************************
  203.  
  204.      tms5220_ready_read -- returns the ready state of the TMS5220
  205.  
  206. ***********************************************************************************************/
  207.  
  208. int tms5220_ready_read(void)
  209. {
  210.     return (fifo_count < FIFO_SIZE-1);
  211. }
  212.  
  213.  
  214.  
  215. /**********************************************************************************************
  216.  
  217.      tms5220_int_read -- returns the interrupt state of the TMS5220
  218.  
  219. ***********************************************************************************************/
  220.  
  221. int tms5220_int_read(void)
  222. {
  223.     return irq_pin;
  224. }
  225.  
  226.  
  227.  
  228. /**********************************************************************************************
  229.  
  230.      tms5220_process -- fill the buffer with a specific number of samples
  231.  
  232. ***********************************************************************************************/
  233.  
  234. void tms5220_process(INT16 *buffer, unsigned int size)
  235. {
  236.     int buf_count=0;
  237.     int i, interp_period;
  238.  
  239. tryagain:
  240.  
  241.     /* if we're not speaking, parse commands */
  242.     while (!speak_external && fifo_count > 0)
  243.         process_command();
  244.  
  245.     /* if there's nothing to do, bail */
  246.     if (!size)
  247.         return;
  248.  
  249.     /* if we're empty and still not speaking, fill with nothingness */
  250.     if (!speak_external)
  251.         goto empty;
  252.  
  253.     /* if we're to speak, but haven't started, wait for the 9th byte */
  254.     if (!talk_status)
  255.     {
  256.         if (fifo_count < 9)
  257.            goto empty;
  258.  
  259.         /* parse but don't remove the first frame, and set the status to 1 */
  260.         parse_frame(0);
  261.         talk_status = 1;
  262.         buffer_empty = 0;
  263.     }
  264.  
  265.     /* loop until the buffer is full or we've stopped speaking */
  266.     while ((size > 0) && speak_external)
  267.     {
  268.         int current_val;
  269.  
  270.         /* if we're ready for a new frame */
  271.         if ((interp_count == 0) && (sample_count == 0))
  272.         {
  273.             /* Parse a new frame */
  274.             if (!parse_frame(1))
  275.                 break;
  276.  
  277.             /* Set old target as new start of frame */
  278.             current_energy = old_energy;
  279.             current_pitch = old_pitch;
  280.             for (i = 0; i < 10; i++)
  281.                 current_k[i] = old_k[i];
  282.  
  283.             /* is this a zero energy frame? */
  284.             if (current_energy == 0)
  285.             {
  286.                 /*printf("processing frame: zero energy\n");*/
  287.                 target_energy = 0;
  288.                 target_pitch = current_pitch;
  289.                 for (i = 0; i < 10; i++)
  290.                     target_k[i] = current_k[i];
  291.             }
  292.  
  293.             /* is this a stop frame? */
  294.             else if (current_energy == (energytable[15] >> 6))
  295.             {
  296.                 /*printf("processing frame: stop frame\n");*/
  297.                 current_energy = energytable[0] >> 6;
  298.                 target_energy = current_energy;
  299.                 speak_external = talk_status = 0;
  300.                 interp_count = sample_count = pitch_count = 0;
  301.  
  302.                 /* generate an interrupt if necessary */
  303.                 set_interrupt_state(1);
  304.  
  305.                 /* try to fetch commands again */
  306.                 goto tryagain;
  307.             }
  308.             else
  309.             {
  310.                 /* is this the ramp down frame? */
  311.                 if (new_energy == (energytable[15] >> 6))
  312.                 {
  313.                     /*printf("processing frame: ramp down\n");*/
  314.                     target_energy = 0;
  315.                     target_pitch = current_pitch;
  316.                     for (i = 0; i < 10; i++)
  317.                         target_k[i] = current_k[i];
  318.                 }
  319.                 /* Reset the step size */
  320.                 else
  321.                 {
  322.                     /*printf("processing frame: Normal\n");*/
  323.                     /*printf("*** Energy = %d\n",current_energy);*/
  324.                     /*printf("proc: %d %d\n",last_fbuf_head,fbuf_head);*/
  325.  
  326.                     target_energy = new_energy;
  327.                     target_pitch = new_pitch;
  328.  
  329.                     for (i = 0; i < 4; i++)
  330.                         target_k[i] = new_k[i];
  331.                     if (current_pitch == 0)
  332.                         for (i = 4; i < 10; i++)
  333.                         {
  334.                             target_k[i] = current_k[i] = 0;
  335.                         }
  336.                     else
  337.                         for (i = 4; i < 10; i++)
  338.                             target_k[i] = new_k[i];
  339.                 }
  340.             }
  341.         }
  342.         else if (interp_count == 0)
  343.         {
  344.             /* Update values based on step values */
  345.             /*printf("\n");*/
  346.  
  347.             interp_period = sample_count / 25;
  348.             current_energy += (target_energy - current_energy) / interp_coeff[interp_period];
  349.             if (old_pitch != 0)
  350.                 current_pitch += (target_pitch - current_pitch) / interp_coeff[interp_period];
  351.  
  352.             /*printf("*** Energy = %d\n",current_energy);*/
  353.  
  354.             for (i = 0; i < 10; i++)
  355.             {
  356.                 current_k[i] += (target_k[i] - current_k[i]) / interp_coeff[interp_period];
  357.             }
  358.         }
  359.  
  360.         if (old_energy == 0)
  361.         {
  362.             /* generate silent samples here */
  363.             current_val = 0x00;
  364.         }
  365.         else if (old_pitch == 0)
  366.         {
  367.             /* generate unvoiced samples here */
  368.             randbit = (rand() % 2) * 2 - 1;
  369.             current_val = (randbit * current_energy) / 4;
  370.         }
  371.         else
  372.         {
  373.             /* generate voiced samples here */
  374.             if (pitch_count < sizeof(chirptable))
  375.                 current_val = (chirptable[pitch_count] * current_energy) / 256;
  376.             else
  377.                 current_val = 0x00;
  378.         }
  379.  
  380.         /* Lattice filter here */
  381.  
  382.         u[10] = current_val;
  383.  
  384.         for (i = 9; i >= 0; i--)
  385.         {
  386.             u[i] = u[i+1] - ((current_k[i] * x[i]) / 32768);
  387.         }
  388.         for (i = 9; i >= 1; i--)
  389.         {
  390.             x[i] = x[i-1] + ((current_k[i-1] * u[i-1]) / 32768);
  391.         }
  392.  
  393.         x[0] = u[0];
  394.  
  395.         /* clipping, just like the chip */
  396.  
  397.         if (u[0] > 511)
  398.             buffer[buf_count] = 127<<8;
  399.         else if (u[0] < -512)
  400.             buffer[buf_count] = -128<<8;
  401.         else
  402.             buffer[buf_count] = u[0] << 6;
  403.  
  404.         /* Update all counts */
  405.  
  406.         size--;
  407.         sample_count = (sample_count + 1) % 200;
  408.  
  409.         if (current_pitch != 0)
  410.             pitch_count = (pitch_count + 1) % current_pitch;
  411.         else
  412.             pitch_count = 0;
  413.  
  414.         interp_count = (interp_count + 1) % 25;
  415.         buf_count++;
  416.     }
  417.  
  418. empty:
  419.  
  420.     while (size > 0)
  421.     {
  422.         buffer[buf_count] = 0x00;
  423.         buf_count++;
  424.         size--;
  425.     }
  426. }
  427.  
  428.  
  429.  
  430. /**********************************************************************************************
  431.  
  432.      process_command -- extract a byte from the FIFO and interpret it as a command
  433.  
  434. ***********************************************************************************************/
  435.  
  436. static void process_command(void)
  437. {
  438.     unsigned char cmd;
  439.  
  440.     /* if there are stray bits, ignore them */
  441.     if (bits_taken)
  442.     {
  443.         bits_taken = 0;
  444.         fifo_count--;
  445.         fifo_head = (fifo_head + 1) % FIFO_SIZE;
  446.     }
  447.  
  448.     /* grab a full byte from the FIFO */
  449.     if (fifo_count > 0)
  450.     {
  451.         cmd = fifo[fifo_head] & 0x70;
  452.         fifo_count--;
  453.         fifo_head = (fifo_head + 1) % FIFO_SIZE;
  454.  
  455.         /* only real command we handle now is speak external */
  456.         if (cmd == 0x60)
  457.         {
  458.             speak_external = 1;
  459.  
  460.             /* according to the datasheet, this will cause an interrupt due to a BE condition */
  461.             if (!buffer_empty)
  462.             {
  463.                 buffer_empty = 1;
  464.                 set_interrupt_state(1);
  465.             }
  466.         }
  467.     }
  468.  
  469.     /* update the buffer low state */
  470.     check_buffer_low();
  471. }
  472.  
  473.  
  474.  
  475. /**********************************************************************************************
  476.  
  477.      extract_bits -- extract a specific number of bits from the FIFO
  478.  
  479. ***********************************************************************************************/
  480.  
  481. static int extract_bits(int count)
  482. {
  483.     int val = 0;
  484.  
  485.     while (count--)
  486.     {
  487.         val = (val << 1) | ((fifo[fifo_head] >> bits_taken) & 1);
  488.         bits_taken++;
  489.         if (bits_taken >= 8)
  490.         {
  491.             fifo_count--;
  492.             fifo_head = (fifo_head + 1) % FIFO_SIZE;
  493.             bits_taken = 0;
  494.         }
  495.     }
  496.     return val;
  497. }
  498.  
  499.  
  500.  
  501. /**********************************************************************************************
  502.  
  503.      parse_frame -- parse a new frame's worth of data; returns 0 if not enough bits in buffer
  504.  
  505. ***********************************************************************************************/
  506.  
  507. static int parse_frame(int removeit)
  508. {
  509.     int old_head, old_taken, old_count;
  510.     int bits, indx, i, rep_flag;
  511.  
  512.     /* remember previous frame */
  513.     old_energy = new_energy;
  514.     old_pitch = new_pitch;
  515.     for (i = 0; i < 10; i++)
  516.         old_k[i] = new_k[i];
  517.  
  518.     /* clear out the new frame */
  519.     new_energy = 0;
  520.     new_pitch = 0;
  521.     for (i = 0; i < 10; i++)
  522.         new_k[i] = 0;
  523.  
  524.     /* if the previous frame was a stop frame, don't do anything */
  525.     if (old_energy == (energytable[15] >> 6))
  526.         return 1;
  527.  
  528.     /* remember the original FIFO counts, in case we don't have enough bits */
  529.     old_count = fifo_count;
  530.     old_head = fifo_head;
  531.     old_taken = bits_taken;
  532.  
  533.     /* count the total number of bits available */
  534.     bits = fifo_count * 8 - bits_taken;
  535.  
  536.     /* attempt to extract the energy index */
  537.     bits -= 4;
  538.     if (bits < 0)
  539.         goto ranout;
  540.     indx = extract_bits(4);
  541.     new_energy = energytable[indx] >> 6;
  542.  
  543.     /* if the index is 0 or 15, we're done */
  544.     if (indx == 0 || indx == 15)
  545.     {
  546.         #ifdef DEBUG_5220
  547.             if (f) fprintf(f, "  (4-bit energy=%d frame)\n",new_energy);
  548.         #endif
  549.  
  550.         /* clear fifo if stop frame encountered */
  551.         if (indx == 15)
  552.         {
  553.             fifo_head = fifo_tail = fifo_count = bits_taken = 0;
  554.             removeit = 1;
  555.         }
  556.         goto done;
  557.     }
  558.  
  559.     /* attempt to extract the repeat flag */
  560.     bits -= 1;
  561.     if (bits < 0)
  562.         goto ranout;
  563.     rep_flag = extract_bits(1);
  564.  
  565.     /* attempt to extract the pitch */
  566.     bits -= 6;
  567.     if (bits < 0)
  568.         goto ranout;
  569.     indx = extract_bits(6);
  570.     new_pitch = pitchtable[indx] / 256;
  571.  
  572.     /* if this is a repeat frame, just copy the k's */
  573.     if (rep_flag)
  574.     {
  575.         for (i = 0; i < 10; i++)
  576.             new_k[i] = old_k[i];
  577.  
  578.         #ifdef DEBUG_5220
  579.             if (f) fprintf(f, "  (11-bit energy=%d pitch=%d rep=%d frame)\n", new_energy, new_pitch, rep_flag);
  580.         #endif
  581.         goto done;
  582.     }
  583.  
  584.     /* if the pitch index was zero, we need 4 k's */
  585.     if (indx == 0)
  586.     {
  587.         /* attempt to extract 4 K's */
  588.         bits -= 18;
  589.         if (bits < 0)
  590.             goto ranout;
  591.         new_k[0] = k1table[extract_bits(5)];
  592.         new_k[1] = k2table[extract_bits(5)];
  593.         new_k[2] = k3table[extract_bits(4)];
  594.         new_k[3] = k4table[extract_bits(4)];
  595.  
  596.         #ifdef DEBUG_5220
  597.             if (f) fprintf(f, "  (29-bit energy=%d pitch=%d rep=%d 4K frame)\n", new_energy, new_pitch, rep_flag);
  598.         #endif
  599.         goto done;
  600.     }
  601.  
  602.     /* else we need 10 K's */
  603.     bits -= 39;
  604.     if (bits < 0)
  605.         goto ranout;
  606.     new_k[0] = k1table[extract_bits(5)];
  607.     new_k[1] = k2table[extract_bits(5)];
  608.     new_k[2] = k3table[extract_bits(4)];
  609.     new_k[3] = k4table[extract_bits(4)];
  610.     new_k[4] = k5table[extract_bits(4)];
  611.     new_k[5] = k6table[extract_bits(4)];
  612.     new_k[6] = k7table[extract_bits(4)];
  613.     new_k[7] = k8table[extract_bits(3)];
  614.     new_k[8] = k9table[extract_bits(3)];
  615.     new_k[9] = k10table[extract_bits(3)];
  616.  
  617.     #ifdef DEBUG_5220
  618.         if (f) fprintf(f, "  (50-bit energy=%d pitch=%d rep=%d 10K frame)\n", new_energy, new_pitch, rep_flag);
  619.     #endif
  620.  
  621. done:
  622.  
  623.     #ifdef DEBUG_5220
  624.         if (f) fprintf(f, "Parsed a frame successfully - %d bits remaining\n", bits);
  625.     #endif
  626.  
  627.     /* if we're not to remove this one, restore the FIFO */
  628.     if (!removeit)
  629.     {
  630.         fifo_count = old_count;
  631.         fifo_head = old_head;
  632.         bits_taken = old_taken;
  633.     }
  634.  
  635.     /* update the buffer_low status */
  636.     check_buffer_low();
  637.     return 1;
  638.  
  639. ranout:
  640.  
  641.     #ifdef DEBUG_5220
  642.         if (f) fprintf(f, "Ran out of bits on a parse!\n");
  643.     #endif
  644.  
  645.     /* this is an error condition; mark the buffer empty and turn off speaking */
  646.     buffer_empty = 1;
  647.     talk_status = speak_external = 0;
  648.     fifo_count = fifo_head = fifo_tail = 0;
  649.  
  650.     /* generate an interrupt if necessary */
  651.     set_interrupt_state(1);
  652.     return 0;
  653. }
  654.  
  655.  
  656.  
  657. /**********************************************************************************************
  658.  
  659.      check_buffer_low -- check to see if the buffer low flag should be on or off
  660.  
  661. ***********************************************************************************************/
  662.  
  663. static void check_buffer_low(void)
  664. {
  665.     /* did we just become low? */
  666.     if (fifo_count < 8)
  667.     {
  668.         /* generate an interrupt if necessary */
  669.         if (!buffer_low)
  670.             set_interrupt_state(1);
  671.         buffer_low = 1;
  672.  
  673.         #ifdef DEBUG_5220
  674.             if (f) fprintf(f, "Buffer low set\n");
  675.         #endif
  676.     }
  677.  
  678.     /* did we just become full? */
  679.     else
  680.     {
  681.         buffer_low = 0;
  682.  
  683.         #ifdef DEBUG_5220
  684.             if (f) fprintf(f, "Buffer low cleared\n");
  685.         #endif
  686.     }
  687. }
  688.  
  689.  
  690.  
  691. /**********************************************************************************************
  692.  
  693.      set_interrupt_state -- generate an interrupt
  694.  
  695. ***********************************************************************************************/
  696.  
  697. static void set_interrupt_state(int state)
  698. {
  699.     if (irq_func && state != irq_pin)
  700.         irq_func(state);
  701.     irq_pin = state;
  702. }
  703.